﻿#include "pch.h"
#include "Logging.h"
#include <iostream>
#include <fstream>
#include <Windows.h>
#include <atomic>
#include <mutex>

namespace
{
    static std::string g_workingDir; // 可选：由外部注入更合适，这里简化
    static std::atomic<Logging::Level> g_minLevel{ Logging::Level::Debug };
    #if defined(_DEBUG)
    static std::atomic<bool> g_consoleEnabled{ true };
    #else
    static std::atomic<bool> g_consoleEnabled{ false };
    #endif
    static std::atomic<bool> g_fileEnabled{ false };
    static std::string g_logFilePath; // 默认空 -> 使用工作目录/log.txt
    static std::mutex g_fileMutex;

    inline std::string GetWorkingDir()
    {
        if (!g_workingDir.empty()) return g_workingDir;
        char buffer[MAX_PATH];
        GetModuleFileNameA(NULL, buffer, MAX_PATH);
        std::string programDir = buffer;
        size_t lastBackslashIndex = programDir.find_last_of("\\");
        g_workingDir = programDir.substr(0, lastBackslashIndex);
        return g_workingDir;
    }

    inline const char* LevelToString(Logging::Level lv)
    {
        switch (lv)
        {
        case Logging::Level::Debug: return "DEBUG";
        case Logging::Level::Info:  return "INFO";
        case Logging::Level::Warn:  return "WARN";
        case Logging::Level::Error: return "ERROR";
        default: return "LOG";
        }
    }
}

namespace Logging
{
    void SetMinLevel(Level level) noexcept { g_minLevel.store(level); }
    void EnableConsole(bool enabled) noexcept {
    #if defined(_DEBUG)
        g_consoleEnabled.store(enabled);
    #else
        // 在 Release 模式下强制关闭控制台输出
        g_consoleEnabled.store(false);
    #endif
    }
    void EnableFile(bool enabled) noexcept { g_fileEnabled.store(enabled); }
    void SetFilePath(const std::string& path) noexcept { g_logFilePath = path; }

    Level GetMinLevel() noexcept { return g_minLevel.load(); }
    bool IsConsoleEnabled() noexcept { return g_consoleEnabled.load(); }
    bool IsFileEnabled() noexcept { return g_fileEnabled.load(); }
    std::string GetFilePath() noexcept { return g_logFilePath; }

    static void WriteConsole(Level level, const std::string& message) noexcept
    {
        if (!g_consoleEnabled.load()) return;
        std::cout << '[' << LevelToString(level) << "] " << message << std::endl;
    }

    static void WriteFile(Level level, const std::string& message) noexcept
    {
        if (!g_fileEnabled.load()) return;
        try
        {
            const std::string filePath = g_logFilePath.empty() ? (GetWorkingDir() + "\\log.txt") : g_logFilePath;
            std::lock_guard<std::mutex> lock(g_fileMutex);
            std::ofstream logFile(filePath, std::ios_base::app);
            SYSTEMTIME sys{}; GetLocalTime(&sys);
            logFile << sys.wYear << '-' << sys.wMonth << '-' << sys.wDay
                    << ' ' << sys.wHour << ':' << sys.wMinute << ':' << sys.wSecond
                    << " [" << LevelToString(level) << "] " << message << std::endl;
        }
        catch (...) { /* 静默失败 */ }
    }

    void Log(Level level, const std::string& message) noexcept
    {
        if (level < g_minLevel.load()) return;
        WriteConsole(level, message);
        WriteFile(level, message);
    }

    // 兼容/便捷重载 -> 默认 Info 级别
    void Log(const char* const message) noexcept { Log(Level::Info, message ? std::string{ message } : std::string{}); }
    void Log(const std::string& message) noexcept { Log(Level::Info, message); }
    void Log(const winrt::hstring& message) noexcept { Log(Level::Info, winrt::to_string(message)); }
    void Log(const std::ostringstream& message) noexcept { Log(Level::Info, message.str()); }
    void Log(int message) noexcept { Log(Level::Info, std::to_string(message)); }

    void LogToFile(const std::string& message) noexcept
    {
        WriteFile(Level::Info, message);
    }
}

